package com.groupbuying.customer.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.google.common.base.Strings;
import com.groupbuying.customer.connector.CurrencyFeign;
import com.groupbuying.customer.connector.SysconfigFeign;
import com.groupbuying.customer.connector.WechatAliFeign;
import com.groupbuying.customer.constants.*;
import com.groupbuying.customer.domain.*;
import com.groupbuying.customer.dto.CustomerInfoApiDTO;
import com.groupbuying.customer.mq.CustomerMQConfig;
import com.groupbuying.customer.pojo.CustomerEnum;
import com.groupbuying.customer.service.*;
import com.groupbuying.customer.utils.JwtUtils;
import com.groupbuying.customer.utils.MD5Utils;
import com.groupbuying.customer.utils.apiresult.ApiResult;
import com.groupbuying.customer.utils.apiresult.ApiResultCode;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: DavidBieber
 * @Email: davidbieber@163.com
 * @Date: 2019-09-27 14:10
 */
@Service
@Transactional(rollbackFor=Exception.class)
public class CustomerAliMainServiceImpl implements CustomerAliMainService {

    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Autowired
    private CurrencyFeign currencyFeign;

    @Autowired
    private CustomerUshopService customerUshopService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private CustomerAccountService customerAccountService;

    @Autowired
    private Producer producer;

    @Autowired
    private CustomerAliinfoRelService customerAliinfoRelService;

    @Autowired
    private WechatAliFeign wechatAliFeign;

    public static final Logger LOGGER= LoggerFactory.getLogger(CustomerAliMainServiceImpl.class);




    @Override
    public ApiResult customerLogin(Map<String, Object> params) {
        //解析map参数
        Object tempParam = params.get("mobile");
        String mobile = tempParam == null ? null : tempParam.toString();
        tempParam = params.get("password");
        String password = tempParam == null ? null : tempParam.toString();
        tempParam = params.get("authcode");
        String authCode = tempParam == null ? null : tempParam.toString();
        LOGGER.info("获取参数信息为:mobile:{},password:{},authCode:{}",mobile,password,authCode);
        //如果获取手机号或密码为空，则返回false
        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
            return ApiResult.paramIsNull();
        }
        //根据会员,查找主库
        CustomerDO customer = customerService.getCustomerModelByLoginNameOrMobileOrEmail(mobile);
        LOGGER.info("根据手机号查询主库信息为:{}",customer);
        //查找余额登录手机号查询优店用户库
        CustomerUshopDO customerUshopDO = customerUshopService.getUshopInfoByMobile(mobile);
        LOGGER.info("根据手机号查询优店库信息为:{}",customer);

        //情况分支，1.主平台和子平台都有
        if (customer != null && customerUshopDO != null) {
            LOGGER.error("1.主平台和子平台都有");
            //重新关联
            customerUshopDO.setMainUuid(customer.getUuid());
            if(Strings.isNullOrEmpty(customerUshopDO.getPassword())){
                customerUshopDO.setPassword(customer.getPassword());
            }
            customerUshopService.update(customerUshopDO);
            //进行优店平台登录流程
            CustomerAccountDO customerAccountDO = customerAccountService.getByCustomerUuid(customer.getUuid());
            return this.uShopLogin(customerAccountDO, customerUshopDO, password, authCode);
        }
        //情况分支，2.主平台有，子平台没有
        if (customer != null && customerUshopDO == null) {
            LOGGER.error("2.主平台有，子平台没有");
            //进行主平台登录流程
            //进行优店平台登录流程
            return this.goyoungLogin(customer, password, authCode);
        }
        //情况分支，3.主平台没有，子平台有
        if (customer == null && customerUshopDO != null) {
            LOGGER.error("3.主平台没有，子平台有");

            //TODO:异步通知主平台创建账号
            Map<String,Object> mqParams = new HashMap<>();
            mqParams.put("userName",mobile);
            mqParams.put("mobile",mobile);
            mqParams.put("password",password);
            LOGGER.info("异步消息体信息为:{}",mqParams);
            Message message = new Message(CustomerMQConfig.GY_TOPIC, CustomerMQConfig.MOBILE_REGISTERED, JSON.toJSONString(mqParams, SerializerFeature.DisableCircularReferenceDetect).getBytes());
            producer.send(message);
            //进行子平台登录
            return this.uShopLogin(null, customerUshopDO, password, authCode);
        }

        //情况分支，4.主平台和子平台都没有
        if (customer == null && customerUshopDO == null) {
            LOGGER.error("用户信息不存在");
            return ApiResult.success(ApiResultCode.LOGINNAMENOTEXISTS, "");
        }
        return null;
    }


    /**
     * 够样主优店登录逻辑
     */
    public ApiResult uShopLogin(CustomerAccountDO customerAccountDO, CustomerUshopDO customerUshopDO, String password, String authCode){
        if(Strings.isNullOrEmpty(customerUshopDO.getPassword())){
            //部分用户孔直接过
        } else if (!customerUshopDO.getPassword().equals(MD5Utils.md5(password))) {
            // 密码校验
            return ApiResult.success(ApiResultCode.PASSWORDERROR, "");
        }
        //开始登录
        try {
            CustomerAliinfoRelDO customerAliinfoRelDO = customerAliinfoRelService.get(customerUshopDO.getCustomerId());
            //根据userID判断
            //调用支付宝授权登录Feign接口获取alipayUserId
            Map<String, String> map = wechatAliFeign.aliGetUserIdAccessCodeByAuthCode(authCode, "youdianproductor");
            if (map == null) {
                return ApiResult.failure("支付宝小程序通过authCode获取alipayUserId为空");
            }
            String aliPayUserId = map.get("alipayUserId");
            LOGGER.info("根据支付宝authCode获取的userId为:{}",aliPayUserId);
            Map<String,Object> searchUserIdMap = new HashMap<>();
            //查询当前登录用户的userID是否在支付宝关系表中，肯定是存在的，因为在一开始的进入小程序就已经注册过了。
            searchUserIdMap.put(CustomerAliinfoRelSearchConstants.SEARCH_ALIPAYUSERID,aliPayUserId);
            searchUserIdMap.put(CustomerAliinfoRelSearchConstants.SEARCH_ISDELETE, CommonConstants.COMMON_FLAG_UNDEL);
            List<CustomerAliinfoRelDO> list = customerAliinfoRelService.list(searchUserIdMap);
            LOGGER.info("根据支付宝用户ID查询到的支付宝账户信息为:{}",list);
            if(list == null || list.size() == 0){
                //未绑定过支付宝关系
                //创建支付宝关系
                CustomerAliinfoRelDO customerAliinfoRelDOInfo = new CustomerAliinfoRelDO();
                customerAliinfoRelDOInfo.setCustomerId(customerUshopDO.getCustomerId());
                customerAliinfoRelDOInfo.setIsDelete(CommonConstants.COMMON_FLAG_UNDEL);
                customerAliinfoRelDOInfo.setGmtCreate(new Date());
                customerAliinfoRelDOInfo.setGmtModified(new Date());
                customerAliinfoRelDOInfo.setAlipayUserid(aliPayUserId);
                LOGGER.info("创建支付宝绑定信息为:{}",customerAliinfoRelDOInfo);
                customerAliinfoRelService.save(customerAliinfoRelDOInfo);
            } else {
                //代表当前通过手机号查询的用户，没有绑定支付宝关系
                if (customerAliinfoRelDO == null){
                    CustomerAliinfoRelDO customerAliinfoRelDOInfo = list.get(0);
                    customerAliinfoRelDO.setCustomerId(customerUshopDO.getCustomerId());
                    customerAliinfoRelService.updateByAliUserId(customerAliinfoRelDOInfo);
                }else if(!customerAliinfoRelDO.getAlipayUserid().equals(aliPayUserId)){
                    //获取此userID对应的用户
                    CustomerAliinfoRelDO customerAliinfoRelDOInfo = list.get(0);
                    LOGGER.info("根据支付宝用户ID查询到的支付宝账户信息为:{}",customerAliinfoRelDOInfo);
                    CustomerUshopDO customerUshopDOInfo = customerUshopService.get(customerAliinfoRelDOInfo.getCustomerId());
                    //登录账号与绑定账号不符
                    return ApiResult.failure(-1,"当前支付宝绑定够样账号为：" + customerUshopDOInfo.getMobile() + ",请用该账号登录","");
                }
            }

            Map<String,Object> result = new HashMap<>();
            //授权
            UserToken userToken = new UserToken(customerUshopDO.getMobile(), customerUshopDO.getCustomerId(), "");
            //过期天数
            String token = JwtUtils.generateToken(userToken, CommonConstants.COMMON_TOKEN_DAY * 24 * 60 * 60 * 1000);
            LOGGER.info("生成时限token为:{}",token);
            result.put("token", token);

            // 查询积分账户
            Map<String,Object> currencyMap = new HashMap<>();
            currencyMap.put("customerId", customerUshopDO.getCustomerId());
            currencyMap.put("delFlag", CommonConstants.COMMON_FLAG_UNDEL);
            Map res = currencyFeign.getCurrencyAccount(currencyMap);
            LOGGER.info("获取账户积分信息为:{}",res);
            // 查询有无积分账户
            if (res == null) {
                // 创建积分账户
                Map<String,Object> searchMap = new HashMap<>();
                searchMap.put(CustomerUshopSearchConstants.SEARCH_CUSTOMERID, customerUshopDO.getCustomerId());
                res = currencyFeign.createCurrencyCustomer(searchMap);
                LOGGER.info("创建积分账户结果为:{}",res);
            }

            CustomerInfoApiDTO customerInfoApiDTO = new CustomerInfoApiDTO();
            if(null == customerAccountDO){
                //新注册用户没有余额
                customerInfoApiDTO.setAccountBalance(Double.valueOf("0.00"));
            } else {
                customerInfoApiDTO.setAccountBalance(customerAccountDO.getNoaccountbalance());
            }
            customerInfoApiDTO.setCustomerId(customerUshopDO.getCustomerId());
            customerInfoApiDTO.setCurrencyNumber(new BigDecimal(res.get("useCurrency").toString()));
            customerInfoApiDTO.setMobile(customerUshopDO.getMobile());
            customerInfoApiDTO.setNickName(customerUshopDO.getMobile());
            if (res.get("password") == null) {
                //未设置积分支付密码
                customerInfoApiDTO.setIsCurrencyPayWord("0");
            } else {
                //已设置积分支付密码
                customerInfoApiDTO.setIsCurrencyPayWord("1");
            }
            LOGGER.info("积分账户信息为:{}",customerInfoApiDTO);
            result.put("customer", customerInfoApiDTO);
            return ApiResult.success(ApiResultCode.SUCCESS_LOGIN, result);
        } catch (Exception err) {
            err.printStackTrace();
            return ApiResult.failure();
        }
    }

    /**
     * 够样主平台登录逻辑
     */
    public ApiResult goyoungLogin(CustomerDO customer, String password, String authCode){
        //检测会员是否冻结
        if (CustomerEnum.CUSTOMER_FROZENSTATE_FROZEN.equals(customer.getFrozenstate())) {
            LOGGER.error("会员被冻结");
            return ApiResult.success(ApiResultCode.CUSTOMERFROZEN, "");
        }

        //检测会员是否激活
        if (CustomerEnum.CUSTOMER_ACTIVESTATE_UNACTIVATE.equals(customer.getActivestate())) {
            // 如果会员未激活，则返回提示
            LOGGER.error("会员未激活");
            return ApiResult.success(ApiResultCode.CUSTOMERNOACTIVATION, "");
        }

        if (!customer.getPassword().equals(MD5Utils.md5(password))) {
            // 密码校验
            LOGGER.error("密码校验不通过");
            return ApiResult.success(ApiResultCode.PASSWORDERROR, "");
        }

        LOGGER.error("够样校验密码结束");
        try {
            //查询userId关系
            //调用支付宝授权登录Feign接口获取alipayUserId
            Map<String, String> map = wechatAliFeign.aliGetUserIdAccessCodeByAuthCode(authCode, "youdianproductor");
            if (map == null) {
                return ApiResult.failure("支付宝小程序通过authCode获取alipayUserId为空");
            }
            String aliPayUserId = map.get("alipayUserId");
            LOGGER.info("根据支付宝autoCode获取的aliPayUserId为:{}",aliPayUserId);
            Map<String,Object> searchUserIdParams = new HashMap();
            searchUserIdParams.put(CustomerAliinfoRelSearchConstants.SEARCH_ALIPAYUSERID,aliPayUserId);
            searchUserIdParams.put(CustomerAliinfoRelSearchConstants.SEARCH_ISDELETE, CommonConstants.COMMON_FLAG_UNDEL);
            List<CustomerAliinfoRelDO> list = customerAliinfoRelService.list(searchUserIdParams);
            LOGGER.info("根据支付宝aliPayUserId查询的支付宝账户信息为:{}",list);
            CustomerUshopDO customerUshopDO;

            if(list == null || list.size() == 0){
                //未绑定过支付宝关系
                //创建子平台账户
                customerUshopDO = new CustomerUshopDO();
                customerUshopDO.setCustomerId(sysconfigFeign.getCustomerID());
                customerUshopDO.setGmtCreate(new Date());
                customerUshopDO.setGmtModified(new Date());
                customerUshopDO.setIsDelete(CommonConstants.COMMON_FLAG_UNDEL);
                customerUshopDO.setMobile(customer.getMobile());
                customerUshopDO.setPassword(customer.getPassword());
                customerUshopDO.setMainUuid(customer.getUuid());
                LOGGER.info("创建优店账户信息为:{}",customerUshopDO);
                customerUshopService.save(customerUshopDO);

                // 创建支付宝关系
                CustomerAliinfoRelDO customerAliinfoRelDO = new CustomerAliinfoRelDO();
                customerAliinfoRelDO.setCustomerId(customerUshopDO.getCustomerId());
                customerAliinfoRelDO.setIsDelete(CommonConstants.COMMON_FLAG_UNDEL);
                customerAliinfoRelDO.setGmtCreate(new Date());
                customerAliinfoRelDO.setGmtModified(new Date());
                customerAliinfoRelDO.setAlipayUserid(aliPayUserId);
                LOGGER.info("创建支付宝绑定账户信息为:{}",customerAliinfoRelDO);
                customerAliinfoRelService.save(customerAliinfoRelDO);
            } else {
                //已经绑定过支付宝关系
                //更新用户信息
                CustomerAliinfoRelDO customerAliinfoRelDO = list.get(0);
                customerUshopDO = customerUshopService.get(customerAliinfoRelDO.getCustomerId());
                customerUshopDO.setMainUuid(customer.getUuid());
                customerUshopDO.setGmtModified(new Date());
                if(Strings.isNullOrEmpty(customerUshopDO.getMobile())){
                    customerUshopDO.setMobile(customer.getMobile());
                    customerUshopDO.setPassword(customer.getPassword());
                }
                LOGGER.info("更新优店账户信息为:{}",customerUshopDO);
                customerUshopService.update(customerUshopDO);
            }
            Map<String,Object> result = new HashMap<>();
            UserToken userToken = new UserToken(customerUshopDO.getMobile(), customerUshopDO.getCustomerId(), "");
            String token = JwtUtils.generateToken(userToken, CommonConstants.COMMON_TOKEN_DAY * 24 * 60 * 60 * 1000);
            LOGGER.info("生成时限授权token为:{}",token);
            result.put("token", token);

            // 查询积分账户
            Map<String,Object> currencyMap = new HashMap();
            currencyMap.put("customerId", customerUshopDO.getCustomerId());
            currencyMap.put("delFlag", CommonConstants.COMMON_FLAG_UNDEL);
            Map res = currencyFeign.getCurrencyAccount(currencyMap);
            LOGGER.info("获取积分账户信息为:{}",res);
            // 查询有无积分账户
            if (res == null) {
                // 创建积分账户
                Map<String,Object> searchMap = new HashMap<>();
                searchMap.put("customerId", customerUshopDO.getCustomerId());
                res = currencyFeign.createCurrencyCustomer(searchMap);
                LOGGER.info("创建积分账户结果为:{}",res);
            }

            CustomerInfoApiDTO customerInfoApiDTO = new CustomerInfoApiDTO();
            CustomerAccountDO customerAccountDO = customerAccountService.getByCustomerUuid(customer.getUuid());
            if(null == customerAccountDO){
                //新注册用户没有余额
                customerInfoApiDTO.setAccountBalance(Double.valueOf("0.00"));
            } else {
                customerInfoApiDTO.setAccountBalance(customerAccountDO.getNoaccountbalance());
            }

            customerInfoApiDTO.setCustomerId(customerUshopDO.getCustomerId());
            customerInfoApiDTO.setCurrencyNumber(new BigDecimal(res.get("useCurrency").toString()));
            customerInfoApiDTO.setMobile(customerUshopDO.getMobile());
            customerInfoApiDTO.setNickName(customerUshopDO.getMobile());
            if (res.get("password") == null) {
                customerInfoApiDTO.setIsCurrencyPayWord("0");
            } else {
                customerInfoApiDTO.setIsCurrencyPayWord("1");
            }
            LOGGER.info("积分账户信息为:{}",customerInfoApiDTO);
            result.put("customer", customerInfoApiDTO);

            return ApiResult.success(ApiResultCode.SUCCESS_LOGIN, result);
        } catch (Exception err) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            err.printStackTrace();
            return ApiResult.failure();
        }
    }

    /**
     * 发送的用户中心消费模块的工具方法。
     *
     * @param obj 消息传递对象
     * @Param tag 消息队列tag
     */
    private void sendMsgToMQ(Object obj, String tag) throws Exception {
        //创建子账号平台
        Message message = new Message(CustomerMQConfig.TOPIC, tag,
                JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect).getBytes());
        producer.send(message);
    }
}
